#include <algorithm>

#include "Operator.h"
#include "Query.h"

std::vector <Operator *> LogicalOperators;
std::vector <PhysicalOperator *> PhysicalOperators;

Operator::Operator(std::string n) :
	name(n), properties(PROPERTY_EMPTY)
{
}

int Operator::getOperatorProperties()
{
	return properties;
}

std::string Operator::getName()
{
	return name;
}

void Operator::addCommOps(std::vector <Operator *> &ops)
{
	while (!ops.empty())
	{
		opsComm.push_back(ops.back());
		ops.pop_back();
	}
}

void Operator::setOperatorProperties(int properties)
{
	this->properties = int(this->properties | properties);
}

int Operator::checkProperty(int property)
{
	return this->properties & property;
}

Operator *Operator::findCommOp(Operator *op)
{
	std::vector <Operator *> :: iterator it = std::find(opsComm.begin(), opsComm.end(), op);

	if (it != opsComm.end())
	{
		return *it;
	}

	return 0;
}

OperatorNode::OperatorNode(Operator *o, PhysicalOperator *physOp, Dependencies *dependencies)
	: op(o), physOp(physOp), dependencies(0), label("")
{
}

OperatorNode::OperatorNode(const OperatorNode &node)
{
	op = node.op;
	//physOp->cost = new OperatorCost(*((OperatorCost *)node.cost));
	physOp = node.physOp;

	if (node.dependencies)
	{
		dependencies = new Dependencies(*node.dependencies);
	}
	else
	{
		dependencies = 0;
	}

	label = node.label;
}

OperatorNode::~OperatorNode()
{
	op = 0;

	delete dependencies;
}

void clearOperators()
{
	for (std::vector <Operator *> :: iterator i = LogicalOperators.begin(); i != LogicalOperators.end(); i++)
	{
		delete *i;
	}

	for (std::vector <PhysicalOperator *> :: iterator i = PhysicalOperators.begin(); i != PhysicalOperators.end(); i++)
	{
		delete *i;
	}
}

Operator *findLogicalOperatorbyName(std::string name)
{
	for (std::vector <Operator *> :: iterator i = LogicalOperators.begin(); i != LogicalOperators.end(); i++)
	{
		if ((*i)->getName() == name)
		{
			return *i;
		}
	}

	return 0;
}

void findPhysicalOperatorbyName(std::string name, std::vector <PhysicalOperator *> &list)
{
	for (std::vector <PhysicalOperator *> :: iterator i = PhysicalOperators.begin(); i != PhysicalOperators.end(); i++)
	{
		if ((*i)->op->getName() == name)
		{
			list.push_back(*i);
		}
	}
}

Query *findOperatorNodeinQuery(Query *query, OperatorNode *node)
{
	if (query->node == node)
	{
		return query;
	}

	for (std::vector <Query *> :: iterator i = query->lists.begin(); i != query->lists.end(); ++i)
	{
		Query *q = findOperatorNodeinQuery(*i, node);
		if (q)
		{
			return q;
		}
	}

	return 0;
}

OperatorNode *findOperatorNode(Query *query, std::string label)
{
	if (query->node->label == label)
	{
		return query->node;
	}

	for (std::vector<Query *>::iterator i = query->lists.begin(); i != query->lists.end(); ++i)
	{
		OperatorNode *node = findOperatorNode(*i, label);
		if (node)
		{
			return node;
		}
	}

	return 0;
}

PhysicalOperator::PhysicalOperator(std::string realizationName, Operator *op, Cost *cost)
	: realizationName(realizationName), op(op), cost(cost)
{
}

PhysicalOperator::~PhysicalOperator()
{
	delete cost;
}